package project.simulation.listeners;

import java.util.HashMap;
import java.util.Vector;

//import layers.agents.PackageAgent;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.general.DatasetUtilities;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;

//import events.SimulationStoppedEvent;
import project.events.packageEvents.PackageCreatedEvent;
import project.events.packageEvents.PackageDeliveredEvent;
import project.events.packageEvents.PackagePickedEvent;
import project.testenvironment.TestingParameters;
//import events.packageEvents.PackageReceivedIntentEvent;
import framework.core.VirtualClock;
import framework.events.Event;
import framework.events.EventBroker;
import framework.events.EventListener;

public class PackageListener extends ApplicationFrame implements EventListener{

	private static final long serialVersionUID = 2173182162536280232L;
	private HashMap<Integer, Double> created, intent, pickup, delivery;
	private int amountOfDeliveredPackages = 0;
	private int amountOfUndeliveredPackages = 0;

	public PackageListener(String title){
		super(title);
		initialize();
		EventBroker.getEventBroker().register(this);
	}

	private void initialize(){
		created = new HashMap<Integer, Double>();
		intent = new HashMap<Integer, Double>();
		pickup = new HashMap<Integer, Double>();
		delivery = new HashMap<Integer, Double>();
	}

	@Override
	public void handleEvent(Event event) {
		if(event instanceof PackageCreatedEvent){
			PackageCreatedEvent e = (PackageCreatedEvent) event;
			this.handlePackageCreatedEvent(e);
		}
//		else if(event instanceof PackageReceivedIntentEvent){
//			PackageReceivedIntentEvent e = (PackageReceivedIntentEvent) event;
//			this.handlePackageReceivedIntentEvent(e);
//		}
		else if(event instanceof PackagePickedEvent){
			PackagePickedEvent e = (PackagePickedEvent) event;
			this.handlePackagePickedEvent(e);
		}
		else if(event instanceof PackageDeliveredEvent){
			PackageDeliveredEvent e = (PackageDeliveredEvent) event;
			this.handlePackageDeliveredEvent(e);
		}
//		else if(event instanceof SimulationStoppedEvent){
//			this.handleSimulationStoppedEvent();
//		}
	}

	private void handleSimulationStoppedEvent() {
		final CategoryDataset dataset = createDataset();
		final JFreeChart chart = createChart(dataset);
		final ChartPanel chartPanel = new ChartPanel(chart);
		chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
		setContentPane(chartPanel);
		this.pack();
		RefineryUtilities.centerFrameOnScreen(this);
		this.setVisible(true);
	}

	private void handlePackageDeliveredEvent(PackageDeliveredEvent e) {
		Long time = VirtualClock.currentTime();
		this.delivery.put(e.getPackageId(), time.doubleValue());
		amountOfDeliveredPackages++;
		amountOfUndeliveredPackages--;

	}
	private void printDataPickedPackages(){
		double avg = 0;
		double ttp = 0;
		for(Integer packageID : pickup.keySet()){
			ttp = (pickup.get(packageID)-created.get(packageID))/1000d;
			System.out.println("pakket met ID " + packageID + " succesvol opgepikt: time till pickup = " + ttp);
			avg += ttp;
		}
		avg = avg/pickup.keySet().size();
		System.out.println("Nb of sequences:" + TestingParameters.NB_OF_PND_SEQUENCES);
		System.out.println("avg time till pickup: " + avg);
	}
	
	private void handlePackagePickedEvent(PackagePickedEvent e) {
		Long time = VirtualClock.currentTime();
		this.pickup.put(e.getPackageId(), time.doubleValue());
		if(pickup.keySet().size() == created.keySet().size()){
			printDataPickedPackages();
		}
	}

//	private void handlePackageReceivedIntentEvent(PackageReceivedIntentEvent e) {
//		Long time = VirtualClock.currentTime();
//		this.intent.put(e.getPackageAgent(), time.doubleValue());
//	}

	private void handlePackageCreatedEvent(PackageCreatedEvent e) {
		Long time = VirtualClock.currentTime();
		this.created.put(e.getPackage().getId(), time.doubleValue());
		amountOfUndeliveredPackages++;
//		System.out.println(amountOfUndeliveredPackages);
	}

	private CategoryDataset createDataset() {
		System.out.println("START OF TIMES");
		Vector<Double> times = new Vector<Double>();
//		for(PackageAgent p : delivery.keySet()){
//			times.add((delivery.get(p)-created.get(p))/1000);
//			System.out.println((delivery.get(p)-created.get(p))/1000);
//		}
		
		System.out.println("END OF TIMES");
		System.out.println("START INTENT");
		
//		for(PackageAgent p : intent.keySet()){
//			System.out.println((intent.get(p)-created.get(p))/1000);
//		}
		System.out.println("END OF INTENT");

		System.out.println("START OF PICKUP");
		for(Integer packageID : pickup.keySet()){
			System.out.println((pickup.get(packageID)-created.get(packageID))/1000);
		}

		System.out.println("END OF PICKUP");
		
		double max = 0l;
		for(double time : times)
			if(max<time)
				max = Math.ceil(time);
//		System.out.println("max = "+ max);
		
		System.out.println("max = "+max);
		
		double factor = max/10f;
		

		System.out.println("factor = "+factor);
		
		double[][] data = new double[1][10];
		for(double time : times){
			data[0][(int) Math.floor(time/factor)]++;
		}
		
		String[] interval = new String[10];
		for (int i=0;i<10;i++){
			Double lo = i*factor/1000;
			Double hi = (i+1)*factor/1000;
//			System.out.println(label+" "+i);
			interval[i] = lo.toString()+"-"+hi.toString();
			System.out.println(interval[i]);
		}
		for (int i=0;i<10;i++)
			System.out.println(interval[i]+" : "+data[0][i]);
		
		
		return DatasetUtilities.createCategoryDataset(new String[]{"Time to delivery"}, interval, data);
	}

	private JFreeChart createChart(final CategoryDataset dataset) {  	
		final JFreeChart chart = ChartFactory.createBarChart(
				"Package times",  // chart title
				"Time",                  // domain axis label
				"Frequency",                     // range axis label
				dataset,                     // data
				PlotOrientation.VERTICAL,    // the plot orientation
				true,                        // legend
				true,                        // tooltips
				false                        // urls
		);
		return chart;
	}

	@Override
	public void terminate() {
		//NO-OP
	}
}
